<template>
    <div class="app-container">
        <div class="search-container">
            <el-form ref="queryParamsRef" :inline="true" :model="queryParams" label-width="68px">
                <el-form-item v-if="!userInfo.orgId" label="机构">
                    <select-org-tree
                        :value="queryParams.orgId"
                        class="width-120 mr20"
                        @getTreeSelect="getTreeSelect"
                        @orgNodeClick="orgNodeClick"
                    />
                </el-form-item>
                <el-form-item label="任务名称" prop="jobName">
                    <el-input
                        v-model="queryParams.jobName"
                        clearable
                        placeholder="请输入任务名称"
                        @keyup.enter.native="handleQuery"
                    />
                </el-form-item>
                <!--            <el-form-item label="任务组名" prop="jobGroup">-->
                <!--                <el-select v-model="queryParams.jobGroup" placeholder="请选择任务组名" clearable>-->
                <!--                    <el-option-->
                <!--                        v-for="dict in dict.type.sys_job_group"-->
                <!--                        :key="dict.value"-->
                <!--                        :label="dict.label"-->
                <!--                        :value="dict.value"-->
                <!--                    />-->
                <!--                </el-select>-->
                <!--            </el-form-item>-->
                <el-form-item label="任务状态" prop="status">
                    <el-select v-model="queryParams.status" class="width-120" clearable placeholder="请选择任务状态">
                        <el-option v-for="dict in dictDataMap['sys_job_status']" :key="dict.dictValue"
                                   :label="dict.dictLabel" :value="dict.dictValue"/>
                    </el-select>
                </el-form-item>
                <div class="mr20" style="float: right">
                    <query-form-button @handleQuery="handleQuery" @resetQuery="resetQuery"/>
                </div>
            </el-form>
        </div>
        <el-row :gutter="10" class="mb8">
            <el-col :span="1.5">
                <el-button
                    plain
                    type="primary"
                    @click="handleAdd"
                >新增
                </el-button>
            </el-col>
        </el-row>
        <el-table v-adaptive :border="true" :data="jobList" :header-cell-style="$headerCellStyle"
                  :stripe="true" highlight-current-row>
            <!--            <el-table-column label="任务编号" width="100" align="center" prop="jobId"/>-->
            <el-table-column :show-overflow-tooltip="true" align="center" label="任务名称" prop="jobName"/>
            <!--        <el-table-column label="任务组名" align="center" prop="jobGroup">-->
            <!--            <template #default="scope">-->
            <!--                <dict-tag :options="dict.type.sys_job_group" :value="scope.row.jobGroup"/>-->
            <!--            </template>-->
            <!--        </el-table-column>-->
            <el-table-column :show-overflow-tooltip="true" align="center" label="调用目标字符串" prop="invokeTarget"/>
            <el-table-column :show-overflow-tooltip="true" align="center" label="cron执行表达式" prop="cronExpression"/>
            <el-table-column align="center" label="状态">
                <template #default="scope">
                    <el-switch
                        v-model="scope.row.status"
                        active-value="0"
                        inactive-value="1"
                        @change="handleStatusChange(scope.row)"
                    ></el-switch>
                </template>
            </el-table-column>
            <el-table-column align="center" class-name="small-padding fixed-width" label="操作">
                <template #default="scope">
                    <el-button type="success" @click="handleUpdate(scope.row)">
                        <template #icon>
                            <i-ep-edit/>
                        </template>
                        修改
                    </el-button>
                    <el-button type="danger" @click="handleDelete(scope.row)">
                        <template #icon>
                            <i-ep-delete/>
                        </template>
                        删除
                    </el-button>
                    <el-dropdown class="ml5">
                        <el-button>更多</el-button>
                        <template #dropdown>
                            <el-dropdown-menu>
                                <el-dropdown-item @click="handleRun(scope.row)">执行一次</el-dropdown-item>
                                <el-dropdown-item @click="handleView(scope.row)">任务详细</el-dropdown-item>
                                <el-dropdown-item @click="handleJobLog(scope.row)">调度日志</el-dropdown-item>
                            </el-dropdown-menu>
                        </template>
                    </el-dropdown>
                </template>
            </el-table-column>
        </el-table>
        <pagination v-model:limit="queryParams.pageSize" v-model:page="queryParams.pageNum" :total="total"
                    @pagination="getList"/>

        <el-dialog v-model="isShow" :title="title" width="30%" @closed="onCancel">
            <div class="pr-20">
                <el-form ref="formRef" :model="formData" :rules="rules" class="edit-form" label-width="120px">
                    <el-form-item label="任务名称" prop="jobName">
                        <el-input v-model="formData.jobName" placeholder="任务名称"/>
                    </el-form-item>
                    <el-form-item label="调用目标字符串" prop="invokeTarget">
                        <el-input v-model="formData.invokeTarget" placeholder="调用目标字符串"/>
                    </el-form-item>
                    <el-form-item label="cron表达式" prop="cronExpression">
                        <el-input v-model="formData.cronExpression" placeholder="请输入cron表达式"/>
                    </el-form-item>
                    <div style="width:100%;padding-left: 10px;">
                        <!--                        <div v-if="formData.cronExpression.length > 0">-->
                        <vue3-cron v-model:value="formData.cronExpression" :defaultCron="defaultCron"
                                   @change="changeCron" @onShowError="onShowError"
                                   @clear-input="clearInput"/>
                        <!--                        </div>-->
                    </div>
                </el-form>
            </div>
            <template #footer>
                  <span class="dialog-footer">
                    <el-button @click="onCancel">取 消</el-button>
                    <el-button type="primary" @click="onSubmit">确 定</el-button>
                  </span>
            </template>
        </el-dialog>

        <!-- 调度日志详细 -->
        <el-dialog v-model="logOpen" append-to-body title="调度日志详细" width="70%">
            <div class="app-container">
                <el-form ref="queryForm" :inline="true" :model="queryParams"
                         label-width="68px">
                    <el-form-item label="任务名称" prop="jobName">
                        <el-input
                            v-model="queryParams.jobName"
                            clearable
                            placeholder="请输入任务名称"
                            style="width: 240px"
                            @keyup.enter.native="handleQuery"
                        />
                    </el-form-item>
                    <el-form-item label="执行状态" prop="status">
                        <el-select
                            v-model="queryParams.status"
                            clearable
                            placeholder="请选择执行状态"
                            style="width: 240px"
                        >
                            <el-option
                                v-for="dict in dictDataMap['sys_job_status']"
                                :key="dict.dictValue"
                                :label="dict.dictLabel"
                                :value="dict.dictValue"
                            />
                        </el-select>
                    </el-form-item>
                    <el-form-item label="执行时间">
                        <el-date-picker v-model="dateRange" :unlink-panels="true" end-placeholder="结束日期"
                                        range-separator="截止" start-placeholder="开始日期" type="daterange"
                                        @change="timeChange"></el-date-picker>
                    </el-form-item>
                    <el-form-item>
                        <el-button icon="el-icon-search" type="primary" @click="handleQuery">搜索
                        </el-button>
                        <el-button icon="el-icon-refresh" @click="resetQuery">重置</el-button>
                    </el-form-item>
                </el-form>
                <el-table v-adaptive="900" :border="true" :data="jobLogList"
                          :header-cell-style="$headerCellStyle" :stripe="true" highlight-current-row>
                    <el-table-column align="center" label="日志编号" prop="jobLogId" width="160"/>
                    <el-table-column :show-overflow-tooltip="true" align="center" label="任务名称" prop="jobName"/>
                    <el-table-column :show-overflow-tooltip="true" align="center" label="调用目标字符串"
                                     prop="invokeTarget"/>
                    <el-table-column :show-overflow-tooltip="true" align="center" label="日志信息" prop="jobMessage"/>
                    <el-table-column align="center" label="执行状态" prop="status">
                        <template #default="scope">
                            <dict-data-tag :options="dictDataMap['sys_job_status']" :value="scope.row.status"/>
                        </template>
                    </el-table-column>
                    <el-table-column align="center" label="执行时间" prop="createTime" width="180">
                        <template #default="scope">
                            <span>{{ $parseTime(scope.row.createTime) }}</span>
                        </template>
                    </el-table-column>
                    <el-table-column align="center" label="操作" width="80">
                        <template #default="scope">
                            <el-button
                                type="primary"
                                @click="logHandleView(scope.row)"
                            >
                                <template
                                    #icon>
                                    <i-ep-view/>
                                </template>
                                详细
                            </el-button>
                        </template>
                    </el-table-column>
                </el-table>

                <pagination
                    v-show="logTotal>0"
                    v-model:limit="logQueryParams.pageSize"
                    v-model:page="logQueryParams.pageNum"
                    :total="logTotal"
                    @pagination="logGetList"
                />
                <el-form ref="logFormRef" :model="logForm" label-width="100px" style="margin-top: 50px">
                    <el-row>
                        <el-col :span="12">
                            <el-form-item label="日志序号：">{{ logForm.jobLogId }}</el-form-item>
                            <el-form-item label="任务名称：">{{ logForm.jobName }}</el-form-item>
                        </el-col>
                        <el-col :span="12">
                            <el-form-item label="任务分组：">{{ logForm.jobGroup }}</el-form-item>
                            <el-form-item label="执行时间：">{{ logForm.createTime }}</el-form-item>
                        </el-col>
                        <el-col :span="24">
                            <el-form-item label="调用方法：">{{ logForm.invokeTarget }}</el-form-item>
                        </el-col>
                        <el-col :span="24">
                            <el-form-item label="日志信息：">{{ logForm.jobMessage }}</el-form-item>
                        </el-col>
                        <el-col :span="24">
                            <el-form-item label="执行状态：">
                                <div v-if="logForm.status == 0">正常</div>
                                <div v-else-if="logForm.status == 1">失败</div>
                            </el-form-item>
                        </el-col>
                        <el-col :span="24">
                            <el-form-item v-if="logForm.status == 1" label="异常信息：">{{
                                    logForm.exceptionInfo
                                }}
                            </el-form-item>
                        </el-col>
                    </el-row>
                </el-form>
                <div slot="footer" class="dialog-footer">
                    <el-button @click="logOpen = false">关 闭</el-button>
                </div>
            </div>
        </el-dialog>
    </div>
</template>
<script lang="ts" setup>
import {addJob, changeJobStatus, delJob, getJob, listJob, runJob, updateJob} from "@/api/qrtz/qrtzJob.ts";
import {listJobLog} from "@/api/qrtz/qrtzJobLog.ts";
import Vue3Cron from "@/views/qrtz/index.vue";
import {useDictStoreHook} from "@/store/modules/dict.ts";
import {useUserStoreHook} from "@/store/modules/user.ts";

const {proxy} = getCurrentInstance() as any;
const dictStore = useDictStoreHook();
const useUserStore = useUserStoreHook();
// 登录用户信息
const userInfo = useUserStore.user.userInfo;
let dictDataMap = ref(dictStore.isTypeGetData('sys_job_status', 'sys_common_status'))
const date = proxy.$parseTime(new Date(), "{y}-{m}-{d} ");
const dateRange = ref([date + "00:00:00", date + "23:59:59"]);
//定义子组件需要接收的值
const props = defineProps({
    curRecord: {type: Object, default: null}, // 当前条目
});

const queryParams = ref<any>({
    orgId: userInfo.orgId,
    pageNum: 1,
    pageSize: 10
});

const logQueryParams = ref<any>({
    orgId: userInfo.orgId,
    pageNum: 1,
    pageSize: 10
});

// 注册事件
const emits = defineEmits(["onClose"]);

const jobList = ref([])
// 执行日志
const jobLogList = ref([])
const queryParamsRef = ref()
const total = ref<number>(0)
const logTotal = ref<number>(0)
const isShow = ref(false)
const logOpen = ref(false)
const title = ref("")
// 定义数据
const errList = ref(['', '', '', '']);
const defaultCron = "0 * * * * ?"; // 默认cron表达式
const formRef = ref();
const invokeTarget = ref<string>('')
const logForm = ref<any>({})
// 表单数据
const formData = ref<any>({
    cronExpression: '',
    jobName: '',
    orgId: queryParams.value.orgId,
    jobGroup: 'DEFAULT'
});

function timeChange(e) {
    if (e) {
        dateRange.value = [proxy.$parseTime(e[0], "{y}-{m}-{d} 00:00:00"), proxy.$parseTime(e[1], "{y}-{m}-{d} 23:59:59")]
    }
    logGetList()
}

/** 新增按钮操作 */
function handleAdd() {
    if (!queryParams.value.orgId) {
        return ElMessage.error(proxy.$OrgIdIsEmpty)
    }
    formData.value = {
        orgId: queryParams.value.orgId
    }
    isShow.value = true;
    title.value = "添加任务";
}

const changeCron = (cron, arr) => {
    if (typeof cron !== "string") return false;
    formData.value.cronExpression = cron;
};

const onShowError = (errArr) => {
    errList.value = errArr;
}


// 校验cron表达式
const validateCronExpression = (rule, value, callback) => {
    if (value) {
        try {
            const interval = cronParse.parseExpression(value)
        } catch (e) {
            callback('cron表达式语法错误，请检查')
        }
    } else {
        callback('执行表达式不能为空！')
    }
    callback()
}

// 表单校验
const rules = {
    jobName: [{required: true, max: 20, whitespace: true, message: '调用目标字符串不能为空', trigger: 'blur'}],
    invokeTarget: [{required: true, message: '名称不能为空且不能大于20个字符', trigger: 'blur'}],
    description: [{max: 100, whitespace: true, message: '描述不能大于100个字符', trigger: 'blur'},],
    triggerLogic: [{required: true, message: '请选择触发逻辑', trigger: 'blur'}],
    cronExpression: [
        {required: true, whitespace: true, message: '请选择cron表达式', trigger: 'change'},
        // { validator: validateCronExpression, trigger: ['blur'] }
    ],
}

// 点击取消按钮
const onCancel = () => {
    formRef.value.resetFields();
    isShow.value = false;
};

function clearInput() {
    formData.value.cronExpression = ""
}

// 点击确定按钮
const onSubmit = () => {
    formRef.value.validate(valid => {
        if (valid) {
            if (errList.value.join('').length) {
                console.log('有错误信息');
                let html = '<div>';
                errList.value.forEach(item => {
                    if (item) html += `<p>${item}</p>`;
                })
                html += '</div>';
                console.log(html)
                ElMessageBox.alert(
                    html,
                    '错误提示',
                    {
                        dangerouslyUseHTMLString: true,
                        type: 'warning'
                    }
                )
                return;
            }
            if (formData.value.jobId != undefined) {
                updateJob(formData.value).then(() => {
                    ElMessage.success("修改成功");
                    isShow.value = false;
                    getList();
                });
            } else {
                addJob(formData.value).then(() => {
                    ElMessage.success("新增成功");
                    isShow.value = false;
                    getList();
                });
            }
        }
    });
}

/** 查询定时任务列表 */
function getList() {
    if (!queryParams.value.orgId) {
        return ElMessage.error(proxy.$OrgIdIsEmpty)
    }
    listJob(queryParams.value).then((res: any) => {
        jobList.value = res.rows;
        total.value = res.total;
    });
}

/**
 * 执行一次
 */
function handleRun(row: any) {
    ElMessageBox.confirm('确认要立即执行一次"' + row.jobName + '"任务吗？', {
            confirmButtonText: "确定",
            cancelButtonText: "取消",
            type: "warning",
        }
    ).then(() => {
        return runJob(row.jobId, row.jobGroup);
    }).then(() => {
        ElMessage.success("执行成功");
    }).catch(function () {
        row.status = row.status === "0" ? "1" : "0";
    });
}

/**
 * 任务详情
 */
function handleView(row: any) {
    getJob(row.jobId).then(response => {
        formData.value = response.data;
        isShow.value = true;
    });
}

/**
 * 调度日志
 */
function handleJobLog(row: any) {
    getJob(row.jobId).then(response => {
        invokeTarget.value = response.data.invokeTarget
        logGetList()
    });
}

function logGetList() {
    logQueryParams.value.invokeTarget = invokeTarget.value
    listJobLog(proxy.$addDateRange(logQueryParams.value, dateRange.value)).then((res: any) => {
        jobLogList.value = res.rows;
        logTotal.value = res.total;
        logOpen.value = true
    })
}

function logHandleView(row: any) {
    logForm.value = row
}

/** 搜索按钮操作 */
function handleQuery() {
    queryParams.value.pageNum = 1;
    getList();
}

/** 重置按钮操作 */
function resetQuery() {
    queryParamsRef.value.resetFields();
    handleQuery();
}

// 任务状态修改
function handleStatusChange(row) {
    let text = row.status === "0" ? "启用" : "停用";

    ElMessageBox.confirm('确认要"' + text + '""' + row.jobName + '"任务吗？', {
            confirmButtonText: "确定",
            cancelButtonText: "取消",
            type: "warning",
        }
    ).then(() => {
        return changeJobStatus(row.jobId, row.status);
    }).then(() => {
        ElMessage.success(text + "成功");
    }).catch(function () {
        row.status = row.status === "0" ? "1" : "0";
    });
}

/** 修改按钮操作 */
function handleUpdate(row) {
    const jobId = row.jobId
    getJob(jobId).then(response => {
        formData.value = response.data;
        isShow.value = true;
        title.value = "修改任务";
    });
}

/** 删除按钮操作 */
function handleDelete(row) {
    const jobIds = row.jobId
    ElMessageBox.confirm('确认要删除【' + row.jobName + '】任务吗？', {
            confirmButtonText: "重新登录",
            cancelButtonText: "取消",
            type: "warning",
        }
    ).then(() => {
        delJob(jobIds).then(() => {
            getList();
            ElMessage.success("删除成功");
        })
    })
}

/** 查询机构下拉树结构 */
function getTreeSelect(response) {
    if (response) {
        getList();
    }
}


// 机构树点击事件
function orgNodeClick(data, _e) {
    queryParams.value.orgId = data.orgId;
    formData.value.orgId = data.orgId;
    if (queryParams.value.orgId) {
        getList();
    }
}

if (queryParams.value.orgId) {
    getList()
}
</script>

<script lang="ts">
export default {
  name: "Cron",
}
</script>
